#pragma once
#include <initializer_list>
#include <memory>
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#define RAPIDJSON_HAS_STDSTRING 1 
#endif
#include "document.h"
#include "error/en.h"
#include "type.h"
#include "tuple_index.h"

namespace rapidjson {

struct MyInsituStringStream {
    using Ch = char;

    MyInsituStringStream(Ch *src, size_t size) : src_(src), dst_(0), begin_(src), end_(src + size) {}
    //for input stream
    Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
    Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
    size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
    //for output stream
    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); if (dst_ < end_ && dst_ >= begin_) *dst_++ = c; }
    void Flush() {}
    //for 原位解析
    Ch* PutBegin() { return dst_ = src_; }
    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
    //Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
    //void Pop(size_t count) { dst_ -= count; }

    Ch* src_;
    Ch* dst_;
    Ch* begin_;
    Ch* end_;
};

template <typename T>
class has_memberfunc_deserialize  {
    typedef char _Has;
    typedef int _Hasnt;
    template<typename cls, void (cls::*)(const Value &)>
    struct fooMatcher;
    template <typename cls>
    static _Has hasFoo(fooMatcher<cls, &cls::deserialize>*);
    template <typename cls>
    static _Hasnt hasFoo(...);
public:
    static constexpr bool value = (sizeof(hasFoo<T>(nullptr)) == sizeof(_Has));
};

struct Deserializer
{
    //针对unique_ptr的反序列化
    template<typename T, typename D>
    static void deserialize(const Value &value, std::unique_ptr<T, D> &ptr, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 1) {
		if (!value.IsNull()) {
			ptr = std::unique_ptr<T, D>(new T);
			deserialize(value, *ptr);
		}
    }
    //针对shared_ptr的反序列化
    template<typename T>
    static void deserialize(const Value &value, std::shared_ptr<T> &ptr, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 1) {
		if (!value.IsNull()) {
			ptr = std::make_shared<T>();
			deserialize(value, *ptr);
		}
    }
    //针对char[]的反序列化
	template<std::size_t N>
	static void deserialize(const Value &value, char (&arr)[N]) {
        if (value.IsString()) {
            const char *p = value.GetString();
            auto len = std::strlen(p);
            if (len < N - 1 && len > 0) {
                std::memcpy(arr, p, len);
                arr[len] = '\0';
            }
        }
    }
    //针对string的反序列化
    static void deserialize(const Value &value, std::string &str)
    {
        if (value.IsString()) {
            str = std::string(value.GetString(), value.GetStringLength());
        }
    }
    //针对bitset的反序列化
	template<std::size_t N>
	static void deserialize(const Value &value, std::bitset<N> &bits)
    {
		if (value.IsUint64()) {
			bits = value.GetUint64();
		} else if (value.IsString()) {
            try {	//此处要留意如果字符串不是0101这样的二进制格式串会抛出异常
				bits = std::bitset<N>(value.GetString());
			} catch (...) {}
        } else if (value.IsArray()) {
			bits = 0;
            auto arr = value.GetArray();
            for (auto &it : arr) {
				if (it.IsUint()) {
					auto v = it.GetUint();
					if (v > 0 && v <= N)
						bits[v - 1] = true;
				}
			}
		}
	}
    //针对bool的json反序列化
    static void deserialize(const Value &value, bool &v)
    {
        if (value.IsBool()) {
            v = value.GetBool();
        }
    }
    //针对整数的json反序列化
    template<typename T>
	static void deserialize(const Value &value, T &v, typename std::enable_if<std::is_same<char, T>::value
                                                                || std::is_same<uint8_t, T>::value
                                                                || std::is_same<short, T>::value
                                                                || std::is_same<uint16_t, T>::value
                                                                || std::is_enum<T>::value
                                                                || std::is_same<int, T>::value, int>::type = 0)
    {
        if (value.IsInt()) {
            v = static_cast<T>(value.GetInt());
        }
    }
    static void deserialize(const Value &value, uint32_t &v)
    {
        if (value.IsUint()) {
            v = value.GetUint();
        }
    }
    static void deserialize(const Value &value, int64_t &v)
    {
        if (value.IsInt64()) {
            v = value.GetInt64();
        }
    }
    static void deserialize(const Value &value, uint64_t &v)
    {
        if (value.IsUint64()) {
            v = value.GetUint64();
        }
    }
    static void deserialize(const Value &value, float &v)
    {
        if (value.IsFloat()) {
            v = value.GetFloat();
        }
    }
    static void deserialize(const Value &value, double &v)
    {
        if (value.IsDouble()) {
            v = value.GetDouble();
        }
    }

	//针对map<string,string>的反序列化
    template<typename T>
    static void deserialize(const Value &root, T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_same<typename T::key_type, std::string>::value
                                                                            && std::is_same<typename T::mapped_type, std::string>::value, int>::type = 0)
    {
        if (root.IsObject()) {
            t.clear();
            for (auto it = root.MemberBegin(); it != root.MemberEnd(); it++) {
                if (it->value.IsString()) {
                    t.emplace(std::string(it->name.GetString(), it->name.GetStringLength()), std::string(it->value.GetString(), it->value.GetStringLength()));
                }
            }
        }
    }
    //针对map<integer,integer>的反序列化
    template<typename T>
    static void deserialize(const Value &root, T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_integral<typename T::key_type>::value
                                                                            && std::is_integral<typename T::mapped_type>::value, int>::type = 0) 
    {
        if (root.IsObject()) {
            t.clear();
            for (auto it = root.MemberBegin(); it != root.MemberEnd(); it++) {
                if (it->value.IsInt64()) {
                    typename T::key_type k = (typename T::key_type)atoll(it->name.GetString());
                    typename T::mapped_type v = (typename T::mapped_type)it->value.GetInt64();
                    t.emplace(k, v);
                }
            }
        }
    }
    //针对map<integer,map>的反序列化
    template<typename T>
    static void deserialize(const Value &root, T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_integral<typename T::key_type>::value
                                                                            && is_std_map<typename T::mapped_type>::value, int>::type = 0)
    {
        if (root.IsObject()) {
            t.clear();
            for (auto it = root.MemberBegin(); it != root.MemberEnd(); it++) {
                typename T::mapped_type v;
                deserialize(it->value, v);
                if (v.size() > 0) {
                    typename T::key_type k = (typename T::key_type)atoll(it->name.GetString());
                    t.emplace(k, v);
                }
            }
        }
    }
    //针对map<integer,class>的反序列化
    template<typename T>
	static void deserialize(const Value &root, T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_integral<typename T::key_type>::value
                                                                            && is_json_class<typename T::mapped_type>::value
                                                                            && std::is_default_constructible<typename T::mapped_type>::value, int>::type = 0) //反序列化时map的value具有默认构造函数，其他map类型不支持
	{
		if (root.IsArray()) {
			t.clear();
            auto arr = root.GetArray();
            for (auto &it : arr) {
                if (it.IsObject()) {
                    typename T::key_type key;
                    auto itr = it.FindMember(MAP_KEY);
                    if (itr != it.MemberEnd()) {
                        deserialize(itr->value, key);
                    } else {
                        itr = it.FindMember("id");
                        if (itr != it.MemberEnd()) {
                            deserialize(itr->value, key);
                        } else {
                            continue;
                        }
                    }
                    deserialize(it, t[key]);
                }
            }
		}
	}

	//针对set的反序列化
	template<typename K, typename Cmp, typename Alloc>
	static void deserialize(const Value &root, std::set<K, Cmp, Alloc> &t, 
		typename std::enable_if<std::is_default_constructible<K>::value, int>::type = 1)
		//反序列化时set的key应具有默认构造函数
	{
		if (root.IsArray()) {
			t.clear();
            auto arr = root.GetArray();
            for (auto &it : arr) {
                K tmp;
                deserialize(it, tmp);
                t.emplace(std::move(tmp));
            }
		}
	}
    //针对unordered_set的反序列化
    template<typename K, typename Hash, typename Pred, typename Alloc>
    static void deserialize(const Value &root, std::unordered_set<K, Hash, Pred, Alloc> &t, 
        typename std::enable_if<std::is_default_constructible<K>::value, int>::type = 1)
        //反序列化时set的key应具有默认构造函数
    {
        if (root.IsArray()) {
            t.clear();
            auto arr = root.GetArray();
            for (auto &it : arr) {
                K tmp;
                deserialize(it, tmp);
                t.emplace(std::move(tmp));
            }
        }
    }

	//针对array的反序列化
	template<typename T, std::size_t N>
	static void deserialize(const Value &root, std::array<T, N> &t)
	{
		if (root.IsArray()) {
            auto arr = root.GetArray();
            std::size_t i = 0;
            for (auto &it : arr) {
                if (i < N) {
                    deserialize(it, t[i++]);
                } else {
                    break;
                }
            }
		}
	}
    //针对T[N]的反序列化
    template<typename T, std::size_t N>
    static void deserialize(const Value &root, T (&t)[N])
    {
        if (root.IsArray()) {
            auto arr = root.GetArray();
            std::size_t i = 0;
            for (auto &it : arr) {
                if (i < N) {
                    deserialize(it, t[i++]);
                } else {
                    break;
                }
            }
        }
    }

	//针对vector或list的反序列化
	template<typename T>
	static void deserialize(const Value &root, T & t, 
		typename std::enable_if<(is_std_vector<T>::value 
								|| is_std_list<T>::value)
								&& std::is_default_constructible<typename T::value_type>::value, int>::type = 1)
	{
		if (root.IsArray()) {
			t.clear();
            auto arr = root.GetArray();
            for (auto &it : arr) {
                t.emplace_back(typename T::value_type());
				deserialize(it, t.back());
            }
		}
	}

	//此函数主要是为了在解析之前先判断相应的成员是否存在然后再进行反序列化
	template<typename T>
	static void deserialize(const Value &value, T &t, const char *name)
	{
        if (value.IsObject()) {
            auto it = value.FindMember(name);
            if (it != value.MemberEnd())
                deserialize(it->value, t);
        }
	}
	//遍历类的Metas和Names分别对类中的成员json反序列化
	template<int... Indexs, typename TP1, typename TP2>
	static void foreach_tuple(const Value &value, tuple_index<Indexs...> ids, TP1 && names, TP2 && metas)
	{
		std::initializer_list<int>{(deserialize(value, std::get<Indexs>(metas), std::get<Indexs>(names)), 0)...};
	}
	//针对除去json基础类和std容器以及特定类型的json反序列化
	template<typename T>
	static void deserialize(const Value &value, T & t, typename std::enable_if<is_json_class<T>::value && !has_memberfunc_deserialize<T>::value, int>::type = 1)
	{
		foreach_tuple(value, typename make_tuple_index<T::element_size>::type(), t.Names(), t.Metas());
	}
    //针对实现了deserialize接口类的json反序列化
    template<typename T>
    static void deserialize(const Value &value, T & t, typename std::enable_if<is_json_class<T>::value && has_memberfunc_deserialize<T>::value, int>::type = 1)
    {
        t.deserialize(value);
    }
};

//反序列化接口
template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, const char *data, std::size_t size, std::string &errmsg)
{
    if (data == nullptr || size == 0) {
        errmsg = "data is null or size is 0 when deserialize";
        return false;
    }

    Document d;
    if (d.Parse(data, size).HasParseError()) {
        errmsg = GetParseError_En(d.GetParseError());
        return false;
    }
    if (!has_memberfunc_deserialize<T>::value && is_container<T>::value && !d.IsArray()) {
        const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
        errmsg = "need json array data but recv ";
        errmsg += kTypeNames[d.GetType()];
        return false;
    }
    if (!has_memberfunc_deserialize<T>::value && is_json_class<T>::value && !d.IsObject()) {
        const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
        errmsg = "need json object data but recv ";
        errmsg += kTypeNames[d.GetType()];
        return false;
    }
    Deserializer::deserialize(d, t);
    return true;
}
//原位解析,速度会快一些,但会改变data的内容
template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, char *data, std::size_t size, std::string &errmsg)
{
    if (data == nullptr || size <= 0) {
        errmsg = "data is null or size <= 0 when deserialize";
        return false;
    }
    Document d;
    MyInsituStringStream ms(data, size);
    if (d.ParseStream<kParseDefaultFlags | kParseStopWhenDoneFlag | kParseInsituFlag>(ms).HasParseError()) {
    //if (d.ParseInsitu<kParseDefaultFlags | kParseStopWhenDoneFlag>(data).HasParseError()) {
        errmsg = GetParseError_En(d.GetParseError());
        return false;
    }
    if (!has_memberfunc_deserialize<T>::value && is_container<T>::value && !d.IsArray()) {
        const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
        errmsg = "need json array data but recv ";
        errmsg += kTypeNames[d.GetType()];
        return false;
    }
    if (!has_memberfunc_deserialize<T>::value && is_json_class<T>::value && !d.IsObject()) {
        const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
        errmsg = "need json object data but recv ";
        errmsg += kTypeNames[d.GetType()];
        return false;
    }
    Deserializer::deserialize(d, t);
    return true;
}

template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, const std::string &json, std::string &errmsg)
{
    return deserialize(t, json.data(), json.size(), errmsg);
}
template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, std::string &json, std::string &errmsg)
{
    return deserialize(t, &json[0], json.size(), errmsg); //不要使用const_cast<char *>(json.data())否则会被COW机制影响
}

template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, const std::string &json)
{
    std::string err;
    return deserialize(t, json, err);
}
template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, std::string &json)
{
    std::string err;
    return deserialize(t, json, err);
}

template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, const char *data, std::size_t size)
{
    std::string err;
    return deserialize(t, data, size, err);
}
template<typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
static inline bool deserialize(T & t, char *data, std::size_t size)
{
    std::string err;
    return deserialize(t, data, size, err);
}

} //end of namespace rapidjson
